package com.cc.screen;

import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.text.Text;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.FrameGrabber;

import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * ClassName: Recorder
 * Description:
 * @Author gmli
 * @Version 1.0
 */
public class Recorder {
    private String recorderBasePath = ""; // 默认保存路径
    private static final int FRAME_RATE = 30;// 帧率
    private ScheduledThreadPoolExecutor timer;// 定时器
    private ScheduledThreadPoolExecutor timer2;// 定时器
    private ScheduledThreadPoolExecutor timer3;// 定时器
    private FFmpegFrameRecorder recorder;// 录制器
    private boolean stopped = false;
    private ScreenGrabber screenGrabber;
    // private SpeakerGrabber speakerGrabber;
    private AudioGrabber audioGrabber;
    // private MicphoneGrabber micphoneGrabber;

    public void setRecorderBasePath(String basePath) {
        this.recorderBasePath = basePath;
    }

    public String getRecorderBasePath() {
        return this.recorderBasePath;
    }

    public void startRecorder(ImageView imageView, Text timeText,Integer  sort) throws Exception {
        initRecorder(sort);
        timer = new ScheduledThreadPoolExecutor(1);
        timer.scheduleAtFixedRate(new Runnable() {
            long t = 0;

            @Override
            public void run() {
                if (!stopped) {
                    try {
                        Image convert = screenGrabber.startGrabber(recorder);
                        // 更新UI
                        imageView.setImage(convert);
                        t += (1000 / FRAME_RATE);
                        timeText.setText(Utils.getHMS(t));
                        System.out.println(timeText.getText());
                    } catch (FFmpegFrameRecorder.Exception | FrameGrabber.Exception e) {
                        e.printStackTrace();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else if (stopped) {
                    System.out.println("stop recorder");
                    stopRecorder();
                }
            }
        }, 0, 1000 / FRAME_RATE, TimeUnit.MILLISECONDS);

        timer2 = new ScheduledThreadPoolExecutor(1);
        timer2.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                if (!stopped) {
                    try {
                        audioGrabber.startGrabber(recorder);
                    } catch (FFmpegFrameGrabber.Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }, 0, 10, TimeUnit.MILLISECONDS);
    }

    /**
     * 初始化录制器
     *
     * @throws Exception
     */
    public void initRecorder(Integer  sortNo) throws Exception {
        System.out.println("init recorder");
        //捕捉器
        screenGrabber = new ScreenGrabber();
        FFmpegFrameGrabber videoGrabber = screenGrabber.initGrabber(FRAME_RATE);

        audioGrabber = new AudioGrabber();
        audioGrabber.initGrabber();

        if("".equals(recorderBasePath) || recorderBasePath == null){
            recorderBasePath  = Paths.get("").toAbsolutePath().toString();
        }
        // 初始化录制器
        String recorderName = recorderBasePath + "/" + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()) + "_"+sortNo+".mp4";
        recorder = new FFmpegFrameRecorder(recorderName, videoGrabber.getImageWidth(), videoGrabber.getImageHeight(), videoGrabber.getAudioChannels());
        recorder.setFrameRate(FRAME_RATE);// 帧率
        recorder.setFormat("mp4");// 格式
        recorder.setVideoQuality(0);//高质量
        recorder.setVideoOption("crf", "16");//智能分配码率
        recorder.setVideoBitrate(4000000);// 4000000 b/s
        recorder.setVideoOption("preset", "slow");
        recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P); // yuv420p
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_MPEG4);

        recorder.setInterleaved(true); // 设置交错的音频和视频帧
        recorder.setSampleRate(44100);// 采样频率
        recorder.setAudioBitrate(128000); // 音频比特率
        recorder.setAudioChannels(2); // 双通道
        recorder.setAudioOption("crf", "0");
        recorder.setAudioQuality(0); // Highest quality
        recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
        recorder.start();
    }

    public void stopRecorder() {
        System.out.println("stop recorder");
        if (timer != null) {
            timer.shutdownNow();
        }
        if (timer2 != null) {
            timer2.shutdownNow();
        }
        if (timer3 != null) {
            timer3.shutdownNow();
        }
        try {
            if (audioGrabber != null) {
                audioGrabber.stopGrabber();
            }
            if (recorder != null) {
                recorder.stop();
                recorder.release();
            }
            if (screenGrabber != null) {
                screenGrabber.stopGrabber();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public boolean getStopped() {
        return stopped;
    }

    public void setStopped(boolean stopped) {
        this.stopped = stopped;
    }
}
